/*     */ package com.zimbra.cs.fb;
/*     */ 
/*     */ import com.zimbra.common.calendar.ICalTimeZone;
/*     */ import com.zimbra.common.localconfig.KnownKey;
/*     */ import com.zimbra.common.localconfig.LC;
/*     */ import com.zimbra.common.util.Log;
/*     */ import com.zimbra.common.util.ZimbraLog;
/*     */ import com.zimbra.cs.dav.DomUtil;
/*     */ import java.io.IOException;
/*     */ import java.util.Calendar;
/*     */ import java.util.Date;
/*     */ import java.util.GregorianCalendar;
/*     */ import java.util.HashMap;
/*     */ import java.util.LinkedList;
/*     */ import java.util.regex.Matcher;
/*     */ import java.util.regex.Pattern;
/*     */ import org.apache.commons.codec.binary.Base64;
/*     */ import org.apache.commons.httpclient.HttpMethod;
/*     */ import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
/*     */ import org.apache.commons.httpclient.methods.PostMethod;
/*     */ import org.dom4j.Document;
/*     */ import org.dom4j.DocumentHelper;
/*     */ import org.dom4j.Element;
/*     */ import org.dom4j.Namespace;
/*     */ import org.dom4j.QName;
/*     */ import org.dom4j.tree.DefaultDocument;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public class ExchangeMessage
/*     */ {
/*     */   public static final String PUBURL_FIRST_PART = "/public/NON_IPM_SUBTREE/SCHEDULE+ FREE BUSY/EX:";
/*     */   public static final String PUBURL_SECOND_PART = "USER-";
/*     */   public static final String PUBURL_RCPT = "/cn=RECIPIENTS/cn=";
/*     */   public static final String PUBURL_EML = ".EML";
/*     */   public static final String ENCODED_SLASH = "_xF8FF_";
/*     */   public static final String ENCODED_SPACE = "%20";
/*     */   public static final String ENCODED_PLUS = "%2B";
/*     */   public static final String MV_INT = "mv.int";
/*     */   public static final String MV_BIN = "mv.bin.base64";
/*     */   public static final int MINS_IN_DAY = 1440;
/*  81 */   public static final Namespace NS_DAV = Namespace.get("D", "DAV:");
/*  82 */   public static final Namespace NS_XML = Namespace.get("c", "xml:");
/*  83 */   public static final Namespace NS_MSFT = Namespace.get("b", "http://schemas.microsoft.com/mapi/proptag/");
/*  84 */   public static final Namespace NS_WEB_FOLDERS = Namespace.get("e", "urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/");
/*     */   
/*  86 */   public static final QName EL_SET = QName.get("set", NS_DAV);
/*  87 */   public static final QName EL_PROP = QName.get("prop", NS_DAV);
/*  88 */   public static final QName EL_PROPERTYUPDATE = QName.get("propertyupdate", NS_DAV);
/*  89 */   public static final QName EL_V = QName.get("v", NS_XML);
/*     */   
/*  91 */   public static final QName ATTR_DT = QName.get("dt", NS_WEB_FOLDERS);
/*     */   
/*  93 */   public static final QName PR_FREEBUSY_ALL_EVENTS = QName.get("0x68501102", NS_MSFT);
/*  94 */   public static final QName PR_FREEBUSY_ALL_MONTHS = QName.get("0x684F1003", NS_MSFT);
/*  95 */   public static final QName PR_FREEBUSY_BUSY_EVENTS = QName.get("0x68541102", NS_MSFT);
/*  96 */   public static final QName PR_FREEBUSY_BUSY_MONTHS = QName.get("0x68531003", NS_MSFT);
/*  97 */   public static final QName PR_FREEBUSY_EMAIL_ADDRESS = QName.get("0x6849001F", NS_MSFT);
/*  98 */   public static final QName PR_FREEBUSY_END_RANGE = QName.get("0x68480003", NS_MSFT);
/*  99 */   public static final QName PR_FREEBUSY_ENTRYIDS = QName.get("0x36E41102", NS_MSFT);
/* 100 */   public static final QName PR_FREEBUSY_LAST_MODIFIED = QName.get("0x68680040", NS_MSFT);
/* 101 */   public static final QName PR_FREEBUSY_NUM_MONTHS = QName.get("0x68690003", NS_MSFT);
/* 102 */   public static final QName PR_FREEBUSY_OOF_EVENTS = QName.get("0x68561102", NS_MSFT);
/* 103 */   public static final QName PR_FREEBUSY_OOF_MONTHS = QName.get("0x68551003", NS_MSFT);
/* 104 */   public static final QName PR_FREEBUSY_START_RANGE = QName.get("0x68470003", NS_MSFT);
/* 105 */   public static final QName PR_FREEBUSY_TENTATIVE_EVENTS = QName.get("0x68521102", NS_MSFT);
/* 106 */   public static final QName PR_FREEBUSY_TENTATIVE_MONTHS = QName.get("0x68511003", NS_MSFT);
/* 107 */   public static final QName PR_PROCESS_MEETING_REQUESTS = QName.get("0x686D000B", NS_MSFT);
/* 108 */   public static final QName PR_DECLINE_RECURRING_MEETING_REQUESTS = QName.get("0x686E000B", NS_MSFT);
/* 109 */   public static final QName PR_DECLINE_CONFLICTING_MEETING_REQUESTS = QName.get("0x686F000B", NS_MSFT);
/* 110 */   public static final QName PR_CAL_END_TIME = QName.get("0x10C40040", NS_MSFT);
/* 111 */   public static final QName PR_CAL_RECURRING_ID = QName.get("0x10C50040", NS_MSFT);
/* 112 */   public static final QName PR_CAL_REMINDER_NEXT_TIME = QName.get("0x10CA0040", NS_MSFT);
/* 113 */   public static final QName PR_CAL_START_TIME = QName.get("0x10C30040", NS_MSFT);
/* 114 */   public static final QName PR_SUBJECT_A = QName.get("0x0037001E", NS_MSFT);
/*     */   
/* 116 */   public static final QName PR_68410003 = QName.get("0x68410003", NS_MSFT);
/* 117 */   public static final QName PR_6842000B = QName.get("0x6842000B", NS_MSFT);
/* 118 */   public static final QName PR_6843000B = QName.get("0x6843000B", NS_MSFT);
/* 119 */   public static final QName PR_6846000B = QName.get("0x6846000B", NS_MSFT);
/* 120 */   public static final QName PR_684B000B = QName.get("0x684B000B", NS_MSFT);
/*     */   
/* 122 */   private static Pattern SLASH = Pattern.compile("\\/");
/* 123 */   private static Pattern SPACE = Pattern.compile(" ");
/* 124 */   private static Pattern PLUS = Pattern.compile("\\+");
/*     */   protected String mOu;
/*     */   protected String mCn;
/*     */   protected String mMail;
/*     */   
/*     */   public ExchangeMessage(String ou, String cn, String mail)
/*     */   {
/* 131 */     this.mOu = ou;
/* 132 */     this.mCn = cn;
/* 133 */     this.mMail = mail;
/*     */   }
/*     */   
/*     */   protected String getRcpt(KnownKey override) {
/* 137 */     String value = override.value();
/* 138 */     if ((value != null) && (value.length() > 0))
/* 139 */       return "/cn=" + value + "/cn=";
/* 140 */     return "/cn=RECIPIENTS/cn=";
/*     */   }
/*     */   
/*     */   public String getUrl() {
/* 144 */     StringBuilder buf = new StringBuilder("/public/NON_IPM_SUBTREE/SCHEDULE+ FREE BUSY/EX:");
/* 145 */     buf.append(SLASH.matcher(this.mOu).replaceAll("_xF8FF_"));
/* 146 */     buf.append("/").append("USER-");
/* 147 */     buf.append(SLASH.matcher(getRcpt(LC.freebusy_exchange_cn1)).replaceAll("_xF8FF_"));
/* 148 */     buf.append(this.mCn);
/* 149 */     buf.append(".EML");
/*     */     
/* 151 */     String ret = buf.toString();
/* 152 */     ret = SPACE.matcher(ret).replaceAll("%20");
/* 153 */     ret = PLUS.matcher(ret).replaceAll("%2B");
/* 154 */     return ret;
/*     */   }
/*     */   
/*     */   public Document createRequest(FreeBusy fb) {
/* 158 */     Element root = DocumentHelper.createElement(EL_PROPERTYUPDATE);
/* 159 */     root.add(NS_XML);
/* 160 */     root.add(NS_MSFT);
/* 161 */     root.add(NS_WEB_FOLDERS);
/* 162 */     Element prop = root.addElement(EL_SET).addElement(EL_PROP);
/* 163 */     addElement(prop, PR_SUBJECT_A, "USER-" + getRcpt(LC.freebusy_exchange_cn2) + this.mCn);
/* 164 */     addElement(prop, PR_FREEBUSY_START_RANGE, minutesSinceMsEpoch(fb.getStartTime()));
/* 165 */     addElement(prop, PR_FREEBUSY_END_RANGE, minutesSinceMsEpoch(fb.getEndTime()));
/* 166 */     addElement(prop, PR_FREEBUSY_EMAIL_ADDRESS, this.mOu + getRcpt(LC.freebusy_exchange_cn3) + this.mCn);
/*     */     
/*     */ 
/* 169 */     Element allMonths = addElement(prop, PR_FREEBUSY_ALL_MONTHS, null, ATTR_DT, "mv.int");
/* 170 */     Element allEvents = addElement(prop, PR_FREEBUSY_ALL_EVENTS, null, ATTR_DT, "mv.bin.base64");
/* 171 */     Element busyMonths = addElement(prop, PR_FREEBUSY_BUSY_MONTHS, null, ATTR_DT, "mv.int");
/* 172 */     Element busyEvents = addElement(prop, PR_FREEBUSY_BUSY_EVENTS, null, ATTR_DT, "mv.bin.base64");
/* 173 */     Element tentativeMonths = addElement(prop, PR_FREEBUSY_TENTATIVE_MONTHS, null, ATTR_DT, "mv.int");
/* 174 */     Element tentativeEvents = addElement(prop, PR_FREEBUSY_TENTATIVE_EVENTS, null, ATTR_DT, "mv.bin.base64");
/* 175 */     Element oofMonths = addElement(prop, PR_FREEBUSY_OOF_MONTHS, null, ATTR_DT, "mv.int");
/* 176 */     Element oofEvents = addElement(prop, PR_FREEBUSY_OOF_EVENTS, null, ATTR_DT, "mv.bin.base64");
/*     */     
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/* 183 */     addElement(prop, PR_68410003, "0");
/* 184 */     addElement(prop, PR_6842000B, "1");
/* 185 */     addElement(prop, PR_6843000B, "1");
/* 186 */     addElement(prop, PR_6846000B, "1");
/* 187 */     addElement(prop, PR_684B000B, "1");
/* 188 */     addElement(prop, PR_PROCESS_MEETING_REQUESTS, "0");
/* 189 */     addElement(prop, PR_DECLINE_RECURRING_MEETING_REQUESTS, "0");
/* 190 */     addElement(prop, PR_DECLINE_CONFLICTING_MEETING_REQUESTS, "0");
/*     */     
/*     */ 
/* 193 */     long startMonth = millisToMonths(fb.getStartTime());
/* 194 */     long endMonth = millisToMonths(fb.getEndTime());
/*     */     
/* 196 */     FreeBusy.IntervalList consolidated = new FreeBusy.IntervalList(fb.getStartTime(), fb.getEndTime());
/* 197 */     encodeIntervals(fb, startMonth, endMonth, "B", busyMonths, busyEvents, consolidated);
/* 198 */     encodeIntervals(fb, startMonth, endMonth, "T", tentativeMonths, tentativeEvents, consolidated);
/* 199 */     encodeIntervals(fb, startMonth, endMonth, "O", oofMonths, oofEvents, consolidated);
/* 200 */     encodeIntervals(consolidated, startMonth, endMonth, "B", allMonths, allEvents, null);
/* 201 */     return new DefaultDocument(root);
/*     */   }
/*     */   
/*     */   private void encodeIntervals(Iterable<FreeBusy.Interval> fb, long startMonth, long endMonth, String type, Element months, Element events, FreeBusy.IntervalList consolidated) {
/* 205 */     HashMap<Long, LinkedList<Byte>> fbMap = new HashMap();
/* 206 */     for (long i = startMonth; i <= endMonth; i += 1L)
/* 207 */       fbMap.put(Long.valueOf(i), new LinkedList());
/* 208 */     for (FreeBusy.Interval interval : fb) {
/* 209 */       String status = interval.getStatus();
/* 210 */       if (status.equals(type)) {
/* 211 */         long start = interval.getStart();
/* 212 */         long end = interval.getEnd();
/* 213 */         long fbMonth = millisToMonths(start);
/* 214 */         LinkedList<Byte> buf = (LinkedList)fbMap.get(Long.valueOf(fbMonth));
/* 215 */         encodeFb(start, end, buf);
/* 216 */         if (consolidated != null)
/* 217 */           consolidated.addInterval(new FreeBusy.Interval(start, end, "B"));
/*     */       }
/*     */     }
/* 220 */     for (long m = startMonth; m <= endMonth; m += 1L) {
/* 221 */       String buf = "";
/* 222 */       LinkedList<Byte> encodedList = (LinkedList)fbMap.get(Long.valueOf(m));
/* 223 */       if (encodedList.size() > 0) {
/*     */         try {
/* 225 */           byte[] raw = new byte[encodedList.size()];
/* 226 */           for (int i = 0; i < encodedList.size(); i++)
/* 227 */             raw[i] = ((Byte)encodedList.get(i)).byteValue();
/* 228 */           byte[] encoded = Base64.encodeBase64(raw);
/* 229 */           buf = new String(encoded, "UTF-8");
/*     */         } catch (IOException e) {
/* 231 */           ZimbraLog.fb.warn("error converting millis to minutes for month " + m, e);
/* 232 */           continue;
/*     */         }
/*     */       }
/* 235 */       addElement(months, EL_V, Long.toString(m));
/* 236 */       addElement(events, EL_V, buf);
/*     */     }
/*     */   }
/*     */   
/*     */   public HttpMethod createMethod(String uri, FreeBusy fb) throws IOException
/*     */   {
/* 242 */     PostMethod method = new PostMethod(uri) {
/* 243 */       private String PROPPATCH = "PROPPATCH";
/*     */       
/* 245 */       public String getName() { return this.PROPPATCH;
/*     */       }
/* 247 */     };
/* 248 */     Document doc = createRequest(fb);
/* 249 */     byte[] buf = DomUtil.getBytes(doc);
/* 250 */     if (ZimbraLog.fb.isDebugEnabled())
/* 251 */       ZimbraLog.fb.debug(new String(buf, "UTF-8"));
/* 252 */     ByteArrayRequestEntity re = new ByteArrayRequestEntity(buf, "text/xml");
/* 253 */     method.setRequestEntity(re);
/* 254 */     return method;
/*     */   }
/*     */   
/* 257 */   private Element addElement(Element parent, QName name, String text, QName attr, String attrVal) { Element el = parent.addElement(name);
/* 258 */     if (text != null)
/* 259 */       el.setText(text);
/* 260 */     if ((attr != null) && (attrVal != null))
/* 261 */       el.addAttribute(attr, attrVal);
/* 262 */     return el;
/*     */   }
/*     */   
/* 265 */   private Element addElement(Element parent, QName name, String text) { return addElement(parent, name, text, null, null); }
/*     */   
/*     */   protected void encodeFb(long s, long e, LinkedList<Byte> buf) {
/* 268 */     int start = millisToMinutes(s);
/* 269 */     int end = start + (int)((e - s) / 60000L);
/* 270 */     ZimbraLog.fb.debug("Start: %s %d", new Object[] { new Date(s).toGMTString(), Integer.valueOf(start) });
/* 271 */     ZimbraLog.fb.debug("End:   %s %d", new Object[] { new Date(e).toGMTString(), Integer.valueOf(end) });
/*     */     
/*     */ 
/* 274 */     buf.addLast(Byte.valueOf((byte)(start & 0xFF)));
/* 275 */     buf.addLast(Byte.valueOf((byte)(start >> 8 & 0xFF)));
/* 276 */     buf.addLast(Byte.valueOf((byte)(end & 0xFF)));
/* 277 */     buf.addLast(Byte.valueOf((byte)(end >> 8 & 0xFF)));
/*     */   }
/*     */   
/*     */   private int millisToMinutes(long millis) {
/* 281 */     Calendar c = new GregorianCalendar();
/* 282 */     c.setTimeZone(ICalTimeZone.getUTC());
/* 283 */     c.setTime(new Date(millis));
/* 284 */     int days = c.get(5) - 1;
/* 285 */     int hours = 24 * days + c.get(11);
/* 286 */     int minutes = c.get(12);
/* 287 */     return 60 * hours + minutes;
/*     */   }
/*     */   
/*     */   protected long millisToMonths(long millis)
/*     */   {
/* 292 */     Calendar c = new GregorianCalendar();
/* 293 */     c.setTimeZone(ICalTimeZone.getUTC());
/* 294 */     c.setTime(new Date(millis));
/* 295 */     return c.get(1) * 16 + c.get(2) + 1; }
/*     */   
/* 297 */   private static char[] HEX = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   private String minutesSinceMsEpoch(long millis)
/*     */   {
/* 305 */     long mins = (millis / 1000L + 11644473600L) / 60L;
/*     */     
/*     */ 
/* 308 */     StringBuilder buf = new StringBuilder();
/* 309 */     for (int i = 0; i < 8; i++) {
/* 310 */       int b = (int)(mins & 0xF);
/* 311 */       buf.insert(0, HEX[b]);
/* 312 */       mins >>= 4;
/*     */     }
/* 314 */     buf.insert(0, "0x");
/* 315 */     return buf.toString();
/*     */   }
/*     */   
/* 318 */   public String toString() { return this.mMail + ", cn=" + this.mCn + ", ou=" + this.mOu; }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/fb/ExchangeMessage.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */